#include <bits/stdc++.h>
using namespace std;
const int N=100050;
const int M=4000050;
struct Edge{
    int v,next;
}edge[M];
int cnt,head[N];
void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addEdge(int u,int v){
    edge[cnt]=Edge{v,head[u]};
    head[u]=cnt++;
    edge[cnt]=Edge{u,head[v]};
    head[v]=cnt++;
}

int n,m,u,v;
//链表
int pre[N],nex[N];
//连通块
int ans,num[N];
//队列
int q[N];
bool flag[N];
void del(int x){
    nex[pre[x]]=nex[x];
    pre[nex[x]]=pre[x];
}
void bfs(int x){
    //模拟队列
    int hea=0,tai=1;
    q[0]=x;
    while(hea<tai){
        num[ans]++;
        int u=q[hea++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            //标记一下相连的边,后边删除没连的边
            flag[v]=true;
        }
        for(int i=nex[0];i<=n;i=nex[i]){
            //删除链表中未标记的点并入队
            if(!flag[i]){
                del(i);
                q[tai++]=i;
            }
        }
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            flag[v]=false;
        }
    }
}
int main(void){
    scanf("%d%d",&n,&m);
    init();
    while(m--){
        scanf("%d%d",&u,&v);
        addEdge(u,v);
    }
    //双向链表
    for(int i=0;i<=n;i++){
        nex[i]=i+1;
    }
    for(int i=1;i<=n+1;i++){
        pre[i]=i-1;
    }
    //遍历链表
    for(int i=nex[0];i<=n;i=nex[0]){
        //对一个链表中的点进行bfs,每次遍历与他不相邻的点
        //在补图中就是同一个连通块,所以标记这些不相邻的点并在链表中删除
        del(i);
        //连通块++
        ans++;
        bfs(i);
    }
    printf("%d\n",ans);
    sort(num+1,num+ans+1);
    for(int i=1;i<=ans;i++){
        printf("%d ",num[i]);
    }
    printf("\n");
    return 0;
}